package com.weimin.SportAppBackend.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weimin.SportAppBackend.entity.User;
import com.weimin.SportAppBackend.entity.dto.UserQueryDTO;
import com.weimin.SportAppBackend.entity.dto.UserStatusDTO;
import com.weimin.SportAppBackend.entity.vo.LoginVO;
import com.weimin.SportAppBackend.entity.vo.UserPublicVO;
import com.weimin.SportAppBackend.service.UserService;
import com.weimin.SportAppBackend.mapper.UserMapper;
import com.weimin.SportAppBackend.utils.JwtUtil;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
* @author huimin
* @description 针对表【users】的数据库操作Service实现
* @createDate 2025-08-15 12:07:05
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {
    @Resource
    private UserMapper userMapper; // 注入 MyBatis Plus Mapper

    @Resource
    private PasswordEncoder passwordEncoder; // 注入 Spring Security 的密码编码器

    @Resource
    private AuthenticationManager authenticationManager; // 注入 Spring Security 的 AuthenticationManager



    @Resource
    private JwtUtil jwtUtil; // 注入 JWT 工具类


    @Value("${wechat.appid}")
    private String appid;

    @Value("${wechat.secret}")
    private String secret;



    /**
     * 根据微信OpenID查询用户
     *
     * @param openid 微信OpenID
     * @return 用户对象，如果不存在则返回null
     */
    @Override // 变更为公共方法
    public User findUserByOpenid(String openid) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getOpenid, openid);
        return userMapper.selectOne(queryWrapper);
    }

    /**
     * 微信登录业务逻辑
     * 根据微信code获取openid，然后判断用户是否存在。
     * 如果存在则直接登录并返回用户信息和JWT Token。
     * 如果不存在则注册新用户（随机昵称，保存openid），然后登录并返回用户信息和JWT Token。
     * @param code 微信小程序登录凭证
     * @return 包含JWT Token和用户信息的响应DTO
     */
    @Override
    @Transactional // 确保注册和登录的原子性
    public LoginVO wechatLogin(String code) {
        // 1. 根据code获取openid
        String openid = getOpenid(code);
        if (openid == null || openid.isEmpty()) {
            throw new RuntimeException("无法获取微信OpenID，请重试");
        }
        User user = findUserByOpenid(openid);
        // 2. 检查用户是否存在
        if (user == null) {
            // 用户不存在，进行注册
            user = new User();
            user.setOpenid(openid);
            // 随机生成昵称：房主 + 4位随机数
            user.setNickname("驴友" + String.format("%04d", new Random().nextInt(10000)));
            user.setStatus(1); // 默认启用
            // 密码可以为空，因为是微信登录
            boolean saveSuccess = save(user);
            if (!saveSuccess) {
                throw new RuntimeException("微信用户注册失败");
            }
        }
        // 3. 生成JWT Token
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", user.getId());
        // 使用OpenID作为JWT的subject，或者如果用户有手机号，也可以用手机号
        // 这里为了统一，如果用户有手机号，仍然用手机号作为subject，否则用openid
        String jwtSubject = (user.getPhone() != null && !user.getPhone().isEmpty()) ? user.getPhone() : user.getOpenid();
        String token = jwtUtil.generateToken(jwtSubject, claims);

        // 4. 构建返回的DTO
        UserPublicVO userPublicVO = new UserPublicVO();
        // 拷贝属性，排除密码和openid等敏感信息
        BeanUtils.copyProperties(user, userPublicVO);
        userPublicVO.setPhone(user.getPhone()); // 确保手机号字段被拷贝，即使可能为null
        return new LoginVO(token, userPublicVO);
    }



    @Override
    public String getOpenid(String code) {
        String uri = "https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={code}&grant_type=authorization_code";
        RestTemplate restTemplate = new RestTemplate();
        // 封装参数，这里是HashMap
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("appid", appid);
        paramMap.put("secret", secret);
        paramMap.put("code", code);
        String result = restTemplate.getForObject(uri, String.class, paramMap);
        // 使用 FastJSON 解析
        JSONObject jsonObject = JSON.parseObject(result);
        // 获取 openid、session_key
        String openid = jsonObject.getString("openid");
        System.out.println("openid: " + openid);
        return openid;
    }

    @Override
    @Transactional
    public boolean bindPhone(Integer userId, String phone, String code) {
        // 验证码校验逻辑（这里简化处理，实际项目中需要对接短信服务）
        if (!validateSmsCode(phone, code)) {
            throw new RuntimeException("验证码错误或已过期");
        }

        // 检查手机号是否已被其他用户绑定
        User existingUser = findUserByPhone(phone);
        if (existingUser != null && !existingUser.getId().equals(userId)) {
            throw new RuntimeException("该手机号已被其他用户绑定");
        }

        // 更新用户手机号
        User user = getById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        user.setPhone(phone);
        user.setUpdatedAt(new Date());
        return updateById(user);
    }

    @Override
    @Transactional
    public LoginVO phoneLogin(String phone, String code, String password) {
        // 验证码校验逻辑
        if (!validateSmsCode(phone, code)) {
            throw new RuntimeException("验证码错误或已过期");
        }

        User user = findUserByPhone(phone);

        if (user == null) {
            // 用户不存在，进行注册
            user = new User();
            user.setPhone(phone);
            // 如果提供了密码则设置密码，否则可以为空（纯验证码登录）
            if (password != null && !password.isEmpty()) {
                user.setPassword(passwordEncoder.encode(password));
            }
            user.setNickname("驴友" + String.format("%04d", new Random().nextInt(10000)));
            user.setStatus(1);
            user.setCreatedAt(new Date());
            user.setUpdatedAt(new Date());

            boolean saveSuccess = save(user);
            if (!saveSuccess) {
                throw new RuntimeException("用户注册失败");
            }
        } else {
            // 用户存在，如果用户有密码且提供了密码，则验证密码
            if (user.getPassword() != null && !user.getPassword().isEmpty() &&
                    password != null && !password.isEmpty()) {
                if (!passwordEncoder.matches(password, user.getPassword())) {
                    throw new RuntimeException("密码错误");
                }
            }
            // 如果用户没有设置密码或未提供密码，则直接通过验证码登录
        }

        // 生成JWT Token
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", user.getId());
        String token = jwtUtil.generateToken(user.getPhone(), claims);

        // 构建返回的DTO
        UserPublicVO userPublicVO = new UserPublicVO();
        BeanUtils.copyProperties(user, userPublicVO);
        return new LoginVO(token, userPublicVO);
    }

    @Override
    public User findUserByPhone(String phone) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, phone);
        return userMapper.selectOne(queryWrapper);
    }


    @Override
    public IPage<User> getUserList(UserQueryDTO queryDTO) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();

        if (queryDTO.getPhone() != null && !queryDTO.getPhone().isEmpty()) {
            queryWrapper.like(User::getPhone, queryDTO.getPhone());
        }

        if (queryDTO.getNickname() != null && !queryDTO.getNickname().isEmpty()) {
            queryWrapper.like(User::getNickname, queryDTO.getNickname());
        }

        if (queryDTO.getStatus() != null) {
            queryWrapper.eq(User::getStatus, queryDTO.getStatus());
        }

        Page<User> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());
        return userMapper.selectPage(page, queryWrapper);
    }

    @Override
    @Transactional
    public boolean updateUserStatus(UserStatusDTO statusDTO) {
        User user = getById(statusDTO.getId());
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        user.setStatus(statusDTO.getStatus());
        user.setUpdatedAt(new Date());
        return updateById(user);
    }

    @Override
    @Transactional
    public boolean deleteUser(Integer id) {
        User user = getById(id);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 逻辑删除，设置状态为2
        user.setStatus(2);
        user.setUpdatedAt(new Date());
        return updateById(user);
    }

    /**
     * 验证短信验证码（简化实现，实际项目中需要对接短信服务）
     * @param phone 手机号
     * @param code 验证码
     * @return 验证结果
     */
    private boolean validateSmsCode(String phone, String code) {
        // 这里简化处理，实际项目中需要对接短信服务验证验证码
        // 可以集成阿里云短信、腾讯云短信等服务
        return code != null && code.length() == 6;
    }
}




